home *** CD-ROM | disk | FTP | other *** search
/ Collection of Internet / Collection of Internet.iso / msdos / lynx / source / doslynx / src / msdostcp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-25  |  44.4 KB  |  1,672 lines

  1. #ifdef MSDOS
  2. /*
  3.  *    This file was created by Garrett Arch Blythe <blythe@stat1.cc.ukans.edu>
  4.  *    for the sole purpose of porting the WWW library to dos using the
  5.  *    Wattcp Library and Borland C++.  This code will of course aid any
  6.  *    other unix code porting using Berkeley sockets, but it is not fully
  7.  *    functional in the way you would, or should expect due to many Dos
  8.  *    and Wattcp limitations.
  9.  *    No wattcp headers are included to avoid name clashes with the
  10.  *    unix socket inteface.
  11.  */
  12. #include"capalloc.h"
  13. #include"msdostcp.h"
  14. #include<stdio.h>
  15. #include"capstdio.h"
  16. #include<errno.h>
  17. #include<stdlib.h>
  18. #include<string.h>
  19. #include<time.h>
  20.  
  21. #ifdef WWW
  22. /*
  23.  *    A global determining if we will even allow any of these functions
  24.  *    to execute.
  25.  */
  26. extern int i_networked;
  27.  
  28. /*
  29.  *    Things to speed up gethostbyname in WWW.
  30.  */
  31. typedef struct    BeenResolved_tag    {
  32.     char *cp_hostname;
  33.     unsigned long int uli_address;
  34.     struct BeenResolved_tag *BR_next;
  35. }
  36. BeenResolved;
  37.  
  38. BeenResolved *BR_first = NULL;
  39.  
  40. static void freeResolved(void);
  41. /*
  42.  *    To free memory at program exit.
  43.  */
  44. void freeResolved(void)    {
  45.     BeenResolved *BR_old;
  46.  
  47.     while(BR_first != NULL)    {
  48.         BR_old = BR_first;
  49.         BR_first = BR_first->BR_next;
  50.         free(BR_old->cp_hostname);
  51.         free(BR_old);
  52.     }
  53. }
  54.  
  55. #endif /* WWW */
  56.  
  57. /*
  58.  *    Doslynx tracing variable.
  59.  */
  60. #ifndef RELEASE
  61. extern char c_trace;
  62. #endif /* RELEASE */
  63.  
  64. #define get_local_port(sockfd) (512 + sockfd)
  65.  
  66. /*
  67.  *    The global socket_table, other functions may query this table for
  68.  *        information regarding a socket, if called from withing
  69.  *        the msdostcp routines, which set ssi_sockfd to the correct
  70.  *        value of the socket being referenced.
  71.  *    Also, of course, if outside functions have the sockfd returned from
  72.  *        a socket call, they can access the table using its value.
  73.  */
  74. signed short int ssi_sockfd = -1;
  75. socket_info sock_table[MAXSOCKETS];
  76.  
  77. /*
  78.  *    Used for initialization only once.
  79.  */
  80. static char firsttime = 1;
  81.  
  82. static void initialize(void);
  83.  
  84. /*
  85.  *    Function:    initialize
  86.  *    Include File:    none
  87.  *    Purpose:    Correctly start the wattcp kernal, and initialize
  88.  *            our socket interface.
  89.  *    Syntax:        static void initialize(void);
  90.  *    Arguments:    void
  91.  *    Return Value:    void
  92.  *    Remarks/Portability/Dependencies/Restrictions:
  93.  *        This function only callable by functions in this file (static).
  94.  *    Revision History:
  95.  *        11-23-93    created
  96.  */
  97. void initialize(void)    {
  98.     auto int i_counter;
  99.  
  100.     /*
  101.      *    Can't allow access if turned off.
  102.      */
  103.     if(i_networked == 0)    {
  104.         return;
  105.     }
  106.  
  107.     /*
  108.      *     Only do this once.
  109.      */
  110.     if(firsttime == 0)
  111.         return;
  112.     firsttime = 0;
  113.  
  114. #ifndef RELEASE
  115.     if(c_trace)    {
  116.         printf("%s:%d: Initializing Waterloo TCP.\n", __FILE__,
  117.             __LINE__);
  118.     }
  119. #endif /* RELEASE */
  120.  
  121.     /*
  122.      *     Initialize Wattcp.
  123.      *    Put a yield function for background processing, defined by
  124.      *        programmer.
  125.      */
  126.     sock_init();
  127. #ifdef WWW
  128.     sock_yield(NULL, yield);
  129. #endif /* WWW */
  130.  
  131.     /*
  132.      *     Initialize our socket interface.
  133.      *    We will support MAXSOCKETS socket connections because
  134.      *    wattcp only allows that many, I think.
  135.      */
  136.     for(i_counter = 0; i_counter < MAXSOCKETS; i_counter++)    {
  137.         sock_table[i_counter].vp_sockfd = NULL;
  138.         sock_table[i_counter].usi_EOF =
  139.             sock_table[i_counter].usi_IO =
  140.             sock_table[i_counter].usi_OPEN = 0U;
  141.         sock_table[i_counter].uli_read =
  142.             sock_table[i_counter].uli_written = 0UL;
  143.         sock_table[i_counter].uli_bindmyaddr = 0UL;
  144.         sock_table[i_counter].usi_bindmyport = 0U;
  145.         sock_table[i_counter].uc_used = 0U;
  146.         sock_table[i_counter].ssi_backlog = 0;
  147.         sock_table[i_counter].ssip_backlogfd = NULL;
  148.     }
  149.  
  150.     /*
  151.      *    Initialize the random number generator, used to select
  152.      *    port numbers in bind.
  153.      */
  154.     randomize();
  155. }
  156.  
  157.  
  158. /*
  159.  *    Function:    socket
  160.  *    Include File:    msdostcp.h
  161.  *    Purpose:    Specify the type of communication protocol desired.
  162.  *    Syntax:        int socket(int family, int type, int protocol);
  163.  *    Arguments:    family        Specifies an address family with
  164.  *                    which addresses specified in later
  165.  *                    socket operations should be
  166.  *                    interpreted.
  167.  *            type        Specifies the communication semantics.
  168.  *            protocol    Specifies the protocol to be used.
  169.  *    Return Value:
  170.  *            int    On success, return value is a descriptor to
  171.  *                the socket.
  172.  *                On faulure, returns -1, and places the
  173.  *                specific error in the global variable errno.
  174.  *    Remarks/Portability/Dependencies/Restrictions:
  175.  *        Made for Ms-Dos using the Wattcp library to better conform
  176.  *        to Berkeley sockets in the DOSLYNX WWW project.
  177.  *        This function in no way attempts to be fully compatible with
  178.  *        it's unix namesake.  Many families, types, and protocols
  179.  *        are not supported and are not #defined in the header file.
  180.  *        MsDos does not support many errno values.  The one supported
  181.  *        will always be returned regardless of the real reason.
  182.  *    Revision History:
  183.  *        11-23-93    created GB
  184.  *                supports AF_INET, SOCK_STREAM, IPPROTO_TCP
  185.  */
  186. int socket(int family, int type, int protocol)    {
  187.     auto int i_counter;
  188.  
  189.     /*
  190.      *    Can't allow access if turned off.
  191.      */
  192.     if(i_networked == 0)    {
  193.         errno = EMFILE;
  194.         return(-1);
  195.     }
  196.  
  197.     /*
  198.      *     Is this the first time that any of the msdostcp functions
  199.      *    are being called?  If so, intialize wattcp and our socket
  200.      *    interface.
  201.      */
  202.     if(firsttime)
  203.         initialize();
  204.  
  205. #ifndef RELEASE
  206.     if(c_trace)    {
  207.         printf("%s:%d: socket(%d, %d, %d);\n", __FILE__, __LINE__,
  208.             family, type, protocol);
  209.     }
  210. #endif /* RELEASE */
  211.  
  212.     /*
  213.      *    A call to socket only returns a socket descriptor
  214.      *    and makes no connection.  We will set up a table to hold
  215.      *    the protocol, along with a wattcp socket pointer, and
  216.      *    return an integer describing the location of the socket in
  217.      *    our array of socket descriptors.
  218.      *
  219.      *    First, find an open socket in our table.
  220.      */
  221.     for(i_counter = 0; i_counter < MAXSOCKETS; i_counter++)
  222.         if(sock_table[i_counter].uc_used == 0U)
  223.             break;
  224.     if(i_counter == MAXSOCKETS)    {
  225.         errno = EMFILE;
  226.         return(ssi_sockfd = -1);
  227.     }
  228.  
  229.     /*
  230.      *     Now all we do is assing the correct protocol in the
  231.      *    table and return it's integer reference.
  232.      *    Use else ifs to expand this code if further implementation
  233.      *    is required.
  234.      */
  235.     if(family == AF_INET)    {
  236.         sock_table[i_counter].i_family = AF_INET;
  237.         if(type == SOCK_STREAM)    {
  238.             sock_table[i_counter].i_type = SOCK_STREAM;
  239.             if(protocol == IPPROTO_TCP || protocol == 0)    {
  240.                 sock_table[i_counter].i_protocol = IPPROTO_TCP;
  241.                 /*
  242.                  *    Mark the socket as being in use.
  243.                  */
  244.                 sock_table[i_counter].uc_used = 1U;
  245.                 return(ssi_sockfd = i_counter);
  246.             }
  247.         }
  248.     }
  249.  
  250.     /*
  251.      *    Must not be implemented yet!
  252.      */
  253.     errno = EMFILE;
  254.     return(ssi_sockfd = -1);
  255. }
  256.  
  257. /*
  258.  *    Function:    connect
  259.  *    Include File:    msdostcp.h
  260.  *    Purpose:    establish a connection with a server.
  261.  *    Syntax:        int connect(int sockfd, struct sockaddr *servaddr,
  262.  *                int addrlen);
  263.  *    Arguments:    sockfd        the socket descriptor returned by
  264.  *                    a call to socket
  265.  *            servaddr    contains the address family and up
  266.  *                    to 14 bytes of protocol-specific
  267.  *                    address
  268.  *            addrlen        the size of the protocol-specific
  269.  *                    address
  270.  *    Return Value:    int    0 on success.
  271.  *                -1 on failure, and sets errno.
  272.  *    Remarks/Portability/Dependencies/Restrictions:
  273.  *        Made for Ms-Dos using the Wattcp library to better conform
  274.  *        to Berkeley sockets in the DOSLYNX WWW project.
  275.  *        This function in no way attempts to be fully compatible with
  276.  *        it's unix namesake.  Many families, types, and protocols
  277.  *        are not supported and are not #defined in the header file.
  278.  *        MsDos does not support many errno values.  The ones supported
  279.  *        will always be returned regardless of the real reason.
  280.  *    Revision History:
  281.  *        11-29-93    created
  282.  */
  283. int connect(int sockfd, struct sockaddr *servaddr, int addrlen)    {
  284.     auto int sock_status = 0;
  285.  
  286.     /*
  287.      *    Can't allow access if turned off.
  288.      */
  289.     if(i_networked == 0)    {
  290.         errno = EBADF;
  291.         return(-1);
  292.     }
  293.  
  294.     /*
  295.      *    Set the global index
  296.      */
  297.     ssi_sockfd = sockfd;
  298.  
  299. #ifndef RELEASE
  300.     if(c_trace)    {
  301.         printf("%s:%d: connect(%d, servaddr, %d);\n", __FILE__,
  302.             __LINE__, sockfd, addrlen);
  303.     }
  304. #endif /* RELEASE */
  305.  
  306.     /*
  307.      *    Luckily, all sockaddr_* structures have the first 16 bytes
  308.      *    set to the family.
  309.      *    Check the family for validity with the socket descriptor.
  310.      *    Don't want our users mixing up their sockets....
  311.      */
  312.     if(servaddr->sa_family != sock_table[sockfd].i_family)    {
  313.         errno = EBADF;
  314.         return(-1);
  315.     }
  316.  
  317.     /*
  318.      *     Do the connection to the socket of appropriate type.
  319.      *    Add else ifs here to expand the implementation.
  320.      */
  321.     if(sock_table[sockfd].i_family == AF_INET)    {
  322.         if(sock_table[sockfd].i_type == SOCK_STREAM)    {
  323.             if(sock_table[sockfd].i_protocol == IPPROTO_TCP)    {
  324.                 auto struct sockaddr_in *servaddr_in =
  325.                     (struct sockaddr_in *)servaddr;
  326.  
  327.                 /*
  328.                  *     Allocate a tcp socket
  329.                  */
  330.                 if(NULL == (sock_table[sockfd].vp_sockfd =
  331.                     malloc(sizeof(tcp_Socket))))    {
  332.                     errno = EBADF;
  333.                     return(-1);
  334.                 }
  335.  
  336.                 /*
  337.                  *     Open the socket.
  338.                  *    WWW does their code right, but
  339.                  *    Wattcp may not; WWW calls htons
  340.                  *    but Wattcp switches the bytes
  341.                  *    even though it doesn't need to.
  342.                  *    We simply will switch the bytes
  343.                  *    again if WWW defined.
  344.                  */
  345.                 if(tcp_open(sock_table[sockfd].vp_sockfd,
  346.                     get_local_port(sockfd),
  347.                     servaddr_in->sin_addr.s_addr,
  348. #ifdef WWW
  349.                     ntohs(servaddr_in->sin_port),
  350. #else
  351.                     servaddr_in->sin_port,
  352. #endif /* WWW */
  353.                     NULL) == 0)    {
  354.                     errno = EBADF;
  355.                     return(-1);
  356.                 }
  357.  
  358.                 /*
  359.                  *    We will only use binary sockets
  360.                  *    with a nagle algorithm.
  361.                  */
  362.                 sock_mode(sock_table[sockfd].vp_sockfd,
  363.                     TCP_MODE_BINARY);
  364.                 sock_mode(sock_table[sockfd].vp_sockfd,
  365.                     TCP_MODE_NAGLE);
  366.  
  367.                 /*
  368.                  *    Set some of the socket members.
  369.                  */
  370.                 sock_table[sockfd].usi_EOF =
  371.                     sock_table[sockfd].usi_IO =
  372.                     sock_table[sockfd].usi_OPEN = 0U;
  373.                 sock_table[sockfd].uli_read =
  374.                     sock_table[sockfd].uli_written = 0UL;
  375.                 sock_table[sockfd].uli_bindmyaddr = 0UL;
  376.                 sock_table[sockfd].usi_bindmyport = 0U;
  377.  
  378.                 /*
  379.                  *     Wait for remote host verification.
  380.                  *    This will goto sock_err on failure.
  381.                  */
  382.                 sock_wait_established(
  383.                     sock_table[sockfd].vp_sockfd,
  384.                     sock_delay, NULL, &sock_status);
  385.  
  386.                 /*
  387.                  *    Mark that we have an open socket.
  388.                  *     We have a good tcp connection.
  389.                  */
  390.                 sock_table[sockfd].usi_OPEN = 1;
  391.                 return(0);
  392.             }
  393.         }
  394.     }
  395.  
  396.     /*
  397.      *     Must not be implemented yet or goto sock_err!
  398.      *    Free the socket if allocated and correct the table.
  399.      */
  400. sock_err:
  401.     if(sock_status == -1 && sock_table[sockfd].vp_sockfd != NULL)
  402.         fprintf(stderr, "WATTCP:  %s\n", sockerr(sock_table[sockfd].vp_sockfd));
  403.     if(sock_table[sockfd].vp_sockfd != NULL)    {
  404.         free(sock_table[sockfd].vp_sockfd);
  405.         sock_table[sockfd].vp_sockfd = NULL;
  406.     }
  407.     errno = EBADF;
  408.     return(-1);
  409. }
  410.  
  411. /*
  412.  *    Function:    bind
  413.  *    Include File:    msdostcp.h
  414.  *    Purpose:    Binds a name to a socket.
  415.  *    Syntax:        int bind(int sockfd, struct sockaddr *myaddr,
  416.  *                int addrlen);
  417.  *    Arguments:    sockfd    Specifies the socket descriptor of the
  418.  *                socket to be bound.
  419.  *            myaddr    Points to an address structure that specifies
  420.  *                the address to which the socket should be
  421.  *                bound.
  422.  *            addrlen    Specifies the length of the socket address
  423.  *                structure.
  424.  *    Return Value:    int    0    success.
  425.  *                -1    failure, errno is set.
  426.  *    Remarks/Portability/Dependencies/Restrictions:
  427.  *        Made for Ms-Dos using the Wattcp library to better conform
  428.  *        to Berkeley sockets in the DOSLYNX WWW project.
  429.  *        This function in no way attempts to be fully compatible with
  430.  *        it's unix namesake.  Many families, types, and protocols
  431.  *        are not supported and are not #defined in the header file.
  432.  *        MsDos does not support many errno values.  The ones supported
  433.  *        will always be returned regardless of the real reason.
  434.  *    Revision History:
  435.  *        12-09-93    created, always fail
  436.  *        03-17-94    Began modifications to implement bind, listen,
  437.  *                and accept to work in a Berkeley fashion.
  438.  *                No allocation of a wattcp socket will occur
  439.  *                until the call to accept is issued.
  440.  *        03-23-94    Modified so that a port request of zero means
  441.  *                that we assign a valid port number.
  442.  *        03-23-94    Sockets are now actually created in listen,
  443.  *                not accept.
  444.  */
  445. int bind(int sockfd, struct sockaddr *myaddr, int addrlen)    {
  446.  
  447.     /*
  448.      *    Can't allow access if turned off.
  449.      */
  450.     if(i_networked == 0)    {
  451.         errno = EBADF;
  452.         return(-1);
  453.     }
  454.  
  455.  
  456.     /*
  457.      *    set the global index of the current socket being referenced.
  458.      */
  459.     ssi_sockfd = sockfd;
  460.  
  461. #ifndef RELEASE
  462.     if(c_trace)    {
  463.         printf("%s:%d: bind(%d, myaddr, %d);\n", __FILE__, __LINE__,
  464.             sockfd, addrlen);
  465.     }
  466. #endif /* RELEASE */
  467.  
  468.     /*
  469.      *    Luckily, all sockaddr_* structures have the first 16 bytes
  470.      *    set to the family.
  471.      *    Check the family for validity with the socket descriptor.
  472.      *    Don't want our users mixing up their sockets....
  473.      */
  474.     if(myaddr->sa_family != sock_table[sockfd].i_family)    {
  475.         errno = EBADF;
  476.         return(-1);
  477.     }
  478.  
  479.     /*
  480.      *    Make sure that we support a bind of the requested type.
  481.      */
  482.     if(sock_table[sockfd].i_family == AF_INET)    {
  483.         if(sock_table[sockfd].i_type == SOCK_STREAM)    {
  484.             if(sock_table[sockfd].i_protocol == IPPROTO_TCP)
  485.             {
  486.                 auto struct sockaddr_in *bindaddr_in =
  487.                     (struct sockaddr_in *)myaddr;
  488.  
  489.                 /*
  490.                  *    Set some of the socket table members.
  491.                  */
  492.                 sock_table[sockfd].usi_EOF =
  493.                     sock_table[sockfd].usi_IO =
  494.                     sock_table[sockfd].usi_OPEN = 0U;
  495.                 sock_table[sockfd].uli_read =
  496.                     sock_table[sockfd].uli_written = 0UL;
  497.  
  498.                 /*
  499.                  *    If the requested port to bind is 0,
  500.                  *    then we take over and assign one.
  501.                  */
  502.                 if(bindaddr_in->sin_port == 0)    {
  503.                     /*
  504.                      *    Assign the port randomly.
  505.                      */
  506.                     bindaddr_in->sin_port = htons((rand()
  507.                         % (MAX_TCP_PORT -
  508.                         MIN_TCP_PORT)) +
  509.                         MIN_TCP_PORT);
  510.                 }
  511.  
  512.                 /*
  513.                  *    Here, just copy of the requested
  514.                  *    local bind address and port into
  515.                  *    the socket table.
  516.                  */
  517.                 sock_table[sockfd].uli_bindmyaddr =
  518.                     bindaddr_in->sin_addr.s_addr;
  519.                 sock_table[sockfd].usi_bindmyport =
  520.                     bindaddr_in->sin_port;
  521.  
  522.                 /*
  523.                  *    Successfully bound in a round
  524.                  *    about manner.
  525.                  */
  526.                 return(0);
  527.             }
  528.         }
  529.     }
  530.  
  531.     /*
  532.      *    As of yet, not supported.
  533.      */
  534.     errno = EBADF;
  535.     return(-1);
  536. }
  537.  
  538. /*
  539.  *    Function:    listen
  540.  *    Include File:    msdostcp.h
  541.  *    Purpose:    Listens for socket connections and limits the
  542.  *            backlog of incoming connections (perhaps none).
  543.  *    Syntax:        int listen(int sockfd, int backlog);
  544.  *    Arguments:    sockfd    Specifies the socket descriptor to listen on.
  545.  *            backlog    Specifies the maximum number of outstanding
  546.  *                connection requests.
  547.  *    Return Value:
  548.  *            int    0    success, socket is listening.
  549.  *                -1    failure, errno is set
  550.  *    Remarks/Portability/Dependencies/Restrictions:
  551.  *        Made for Ms-Dos using the Wattcp library to better conform
  552.  *        to Berkeley sockets in the DOSLYNX WWW project.
  553.  *        This function in no way attempts to be fully compatible with
  554.  *        it's unix namesake.  Many families, types, and protocols
  555.  *        are not supported and are not #defined in the header file.
  556.  *        MsDos does not support many errno values.  The ones supported
  557.  *        will always be returned regardless of the real reason.
  558.  *    Revision History:
  559.  *        12-09-93    created, always fail
  560.  *        03-17-94    Modifed to succeed, NO BAKCLOG WILL
  561.  *                BE IMPLEMENTED.  Allocation of an actual
  562.  *                wattcp socket is done in accept rather than
  563.  *                here.  The listening socket really needs no
  564.  *                socket at all.
  565.  *        03-23-94    Oddly enough, sometimes a request for a
  566.  *                socket will come in before a call to accept
  567.  *                is made.  In this case, we will need to
  568.  *                create the listening sockets here in listen.
  569.  *                Accept will return those it has ready, or
  570.  *                will in busywait until a connection comes in.
  571.  *                backlog will now be implemented, but the
  572.  *                number requested can not be guaranteed due
  573.  *                to possible memory failures.
  574.  */
  575. int listen(int sockfd, int backlog)    {
  576.     auto int i_counter;
  577.  
  578.     /*
  579.      *    Can't allow access if turned off.
  580.      */
  581.     if(i_networked == 0)    {
  582.         errno = EBADF;
  583.         return(-1);
  584.     }
  585.  
  586.     /*
  587.      *    Set the global index.
  588.      */
  589.     ssi_sockfd = sockfd;
  590.  
  591. #ifndef RELEASE
  592.     if(c_trace)    {
  593.         printf("%s:%d: listen(%d, %d);\n", __FILE__, __LINE__, sockfd,
  594.             backlog);
  595.     }
  596. #endif /* RELEASE */
  597.  
  598.     /*
  599.      *    We can only listen using tcp with WATTCP.
  600.      *    Make sure this is the protocol.
  601.      */
  602.     if(sock_table[sockfd].i_family != AF_INET || sock_table[sockfd].
  603.         i_type != SOCK_STREAM || sock_table[sockfd].i_protocol !=
  604.         IPPROTO_TCP)    {
  605.         errno = EBADF;
  606.         return(-1);
  607.     }
  608.  
  609.  
  610.     /*
  611.      *    Backlog is atleast one, never greater than 5.
  612.      */
  613.     if(backlog < 1)    {
  614.         backlog = 1;
  615.     }
  616.     else if(backlog > 5)    {
  617.         backlog = 5;
  618.     }
  619.  
  620.     /*
  621.      *    Assign the number of possible backlogs and allocate memory
  622.      *    to keep track of which sockets will be in the backlog queue.
  623.      */
  624.     sock_table[sockfd].ssi_backlog = (signed short int)backlog;
  625.     sock_table[sockfd].ssip_backlogfd = (signed short int *)malloc(
  626.         sizeof(signed short int) * backlog);
  627.     if(NULL == sock_table[sockfd].ssip_backlogfd)    {
  628.         errno = EBADF;
  629.         return(-1);
  630.     }
  631.  
  632.     /*
  633.      *    Get our sockets, allocate them.  If unable to allocate one,
  634.      *    close it and put -1 for the it and the rest.
  635.      */
  636.     for(i_counter = 0; i_counter < backlog; i_counter++)    {
  637.         *(sock_table[sockfd].ssip_backlogfd + i_counter) = socket(
  638.             sock_table[sockfd].i_family,
  639.             sock_table[sockfd].i_type,
  640.             sock_table[sockfd].i_protocol);
  641.  
  642.         if(*(sock_table[sockfd].ssip_backlogfd + i_counter) != -1)
  643.         {
  644.             /*
  645.              *    Allocate each valid socket its WATTCP socket.
  646.              */
  647.             sock_table[*(sock_table[sockfd].ssip_backlogfd +
  648.                 i_counter)].vp_sockfd = malloc(sizeof(
  649.                 tcp_Socket));
  650.  
  651.             if(sock_table[*(sock_table[sockfd].ssip_backlogfd +
  652.                 i_counter)].vp_sockfd == NULL)    {
  653.                 s_close(*(sock_table[sockfd].ssip_backlogfd +
  654.                     i_counter));
  655.                 *(sock_table[sockfd].ssip_backlogfd +
  656.                     i_counter) = -1;
  657.                 continue;
  658.             }
  659.  
  660.             /*
  661.              *    Have each one listen.
  662.              *    Do not check establishment.
  663.              *    That is done in accept.
  664.              */
  665.             tcp_listen(sock_table[*(sock_table[sockfd].
  666.                 ssip_backlogfd + i_counter)].vp_sockfd,
  667. #ifdef WWW
  668.                 htons(sock_table[sockfd].usi_bindmyport),
  669. #else
  670.                 sock_tablep[sockfd].usi_bindmyport,
  671. #endif /* WWW */
  672.                 0UL, 0U, NULL, 0U);
  673.         }
  674.     }
  675.  
  676.     /*
  677.      *    It just so happens that if even the very first backlog
  678.      *    socket is not allocated, then this function has failed.
  679.      *    Check.
  680.      */
  681.     if(*(sock_table[sockfd].ssip_backlogfd) == -1)    {
  682.         errno = EBADF;
  683.         return(-1);
  684.     }
  685.  
  686.     /*
  687.      *    Return success.
  688.      */
  689.     return(0);
  690. }
  691.  
  692. /*
  693.  *    Function:    accept
  694.  *    Include File:    msdostcp.h
  695.  *    Purpose:    Accepts a connection on a socket to create a new
  696.  *            socket.
  697.  *    Syntax:        int accept(int sockfd, struct sockaddr *peer,
  698.  *                int *addrlen);
  699.  *    Arguments:
  700.  *            sockfd    specifies a socket created with the socket
  701.  *                subroutine, bound to an address with the
  702.  *                bind subroutine, and that has issued a
  703.  *                successful call to the listen subroutine.
  704.  *            peer    Specifies a result parameter that is filled
  705.  *                in with the address of the connecting entity
  706.  *                as known to the communications layer.
  707.  *            addrlen    Specifies a parameter that initially contains
  708.  *                the amount of space pointed to by the peer
  709.  *                parameter.  Upon return, the parameter contains
  710.  *                the actual length (in bytes) of the address
  711.  *                returned.
  712.  *    Return Value:    int    On successful completion, returns the socket
  713.  *                descriptor of the new socket.
  714.  *                On failure, -1 and sets errno.
  715.  *    Remarks/Portability/Dependencies/Restrictions:
  716.  *        Made for Ms-Dos using the Wattcp library to better conform
  717.  *        to Berkeley sockets in the DOSLYNX WWW project.
  718.  *        This function in no way attempts to be fully compatible with
  719.  *        it's unix namesake.  Many families, types, and protocols
  720.  *        are not supported and are not #defined in the header file.
  721.  *        MsDos does not support many errno values.  The ones supported
  722.  *        will always be returned regardless of the real reason.
  723.  *    Revision History:
  724.  *        12-09-93    created, always fail
  725.  *        03-17-94    Modified to work.  What a slice of hell MSDOS
  726.  *                has cut out for me.
  727.  *        03-23-94    Allocation of the listening sockets moved to
  728.  *                listen.
  729.  */
  730. int accept(int sockfd, struct sockaddr *peer, int *addrlen)    {
  731.     auto int newsockfd = -1;
  732.     auto short int newsock_status = 0;
  733.     auto struct hack_sockaddr hackpeer;
  734.     auto struct sockaddr_in *peer_in;
  735.     auto int i_counter, i_replacefd;
  736.  
  737.     /*
  738.      *    Can't allow access if turned off.
  739.      */
  740.     if(i_networked == 0)    {
  741.         errno = EBADF;
  742.         return(-1);
  743.     }
  744.  
  745.     /*
  746.      *    Set the global index.
  747.      *    Will of course change when we create the new socket.
  748.      */
  749.     ssi_sockfd = sockfd;
  750.  
  751. #ifndef RELEASE
  752.     if(c_trace)    {
  753.         printf("%s:%d: accept(%d, peer, %d);\n", __FILE__, __LINE__,
  754.             sockfd, *addrlen);
  755.     }
  756. #endif /* RELEASE */
  757.  
  758.     /*
  759.      *    We can only listen using tcp with WATTCP.
  760.      *    Make sure this is the protocol.
  761.      */
  762.     if(sock_table[sockfd].i_family == AF_INET)    {
  763.         if(sock_table[sockfd].i_type == SOCK_STREAM)    {
  764.             if(sock_table[sockfd].i_protocol == IPPROTO_TCP)
  765.             {
  766.                 /*
  767.                  *    first off, check to make sure that
  768.                  *    we have sockets listening.
  769.                  */
  770.                 for(i_counter = 0; i_counter < sock_table
  771.                     [sockfd].ssi_backlog; i_counter++)
  772.                 {
  773.                     if(*(sock_table[sockfd].ssip_backlogfd
  774.                         + i_counter) != -1)    {
  775.                         break;
  776.                     }
  777.                 }
  778.  
  779.                 /*
  780.                  *    If no sockets listening, return
  781.                  *    failure.
  782.                  */
  783.                 if(i_counter == sock_table[sockfd].
  784.                     ssi_backlog)    {
  785.                     errno = EBADF;
  786.                     return(-1);
  787.                 }
  788.  
  789.                 /*
  790.                  *    Busy wait until a socket is connected.
  791.                  */
  792.                 while(1)    {
  793.                     for(i_counter = 0; i_counter <
  794.                         sock_table[sockfd].
  795.                         ssi_backlog; i_counter++)
  796.                     {
  797.                         if(*(sock_table[sockfd].
  798.                             ssip_backlogfd +
  799.                             i_counter) == -1)
  800.                         {
  801.                             continue;
  802.                         }
  803.  
  804.                         if(sock_established(sock_table
  805.                             [*(sock_table[sockfd].
  806.                             ssip_backlogfd +
  807.                             i_counter)].vp_sockfd)
  808.                             != 0)    {
  809.                             break;
  810.                         }
  811.                     }
  812.  
  813.                     /*
  814.                      *    break loop, have established.
  815.                      */
  816.                     if(i_counter != sock_table[sockfd].
  817.                         ssi_backlog)    {
  818.                         break;
  819.                     }
  820.                 }
  821.  
  822.                 newsockfd = *(sock_table[sockfd].
  823.                     ssip_backlogfd + i_counter);
  824.  
  825.                 /*
  826.                  *    create a new socket to listen
  827.                  *    in place of the established socket.
  828.                  */
  829.                 i_replacefd = socket(
  830.                     sock_table[sockfd].i_family,
  831.                     sock_table[sockfd].i_type,
  832.                     sock_table[sockfd].i_protocol);
  833.  
  834.                 /*
  835.                  *    if we have a replacement, allocate
  836.                  *    memory for it.
  837.                  */
  838.                 if(i_replacefd != -1)    {
  839.                     if(NULL == (sock_table[i_replacefd].
  840.                         vp_sockfd =
  841.                         malloc(sizeof(tcp_Socket))))
  842.                     {
  843.                         s_close(i_replacefd);
  844.                         i_replacefd = -1;
  845.                     }
  846.                     else    {
  847.                         /*
  848.                          *    Have the replacement
  849.                          *    listen also.
  850.                          */
  851.                         tcp_listen(sock_table[
  852.                             i_replacefd].
  853.                             vp_sockfd,
  854. #ifdef WWW
  855.                             htons(
  856.                             sock_table
  857.                             [sockfd].
  858.                             usi_bindmyport),
  859. #else
  860.                             sock_table[sockfd].
  861.                             usi_bindmyport,
  862. #endif /* WWW */
  863.                             0UL,
  864.                             0U, NULL, 0U);
  865.                     }
  866.                 }
  867.  
  868.                 /*
  869.                  *    Put the replacement in the listen
  870.                  *    queue.  May be -1.
  871.                  */
  872.                 *(sock_table[sockfd].ssip_backlogfd +
  873.                     i_counter) = i_replacefd;
  874.  
  875.                 /*
  876.                  *    Call a wattcp function to get the
  877.                  *    peer information.
  878.                  */
  879.                 *addrlen = sizeof(struct hack_sockaddr);
  880.                 getpeername(sock_table[newsockfd].vp_sockfd,
  881.                     &hackpeer, addrlen);
  882.  
  883.                 /*
  884.                  *    Copy over the peer information.
  885.                  *    Assume a sockaddr_in structure for
  886.                  *    peer.
  887.                  */
  888.                 peer_in = (struct sockaddr_in *)peer;
  889.                 peer_in->sin_port = hackpeer.s_port;
  890.                 peer_in->sin_addr.s_addr =
  891.                     hackpeer.s_ip;
  892.                 peer_in->sin_family = AF_INET;
  893.  
  894.                 /*
  895.                  *    Since doing a tcp socket, return
  896.                  *    the size of the tcp sockaddr in
  897.                  *    addrlen.
  898.                  */
  899.                 *addrlen = sizeof(struct sockaddr_in);
  900.  
  901.                 /*
  902.                  *    Okay, return the established socket.
  903.                  */
  904.                 return(newsockfd);
  905.             }
  906.         }
  907.     }
  908.  
  909.     /*
  910.      *    Not supported.
  911.      */
  912.     errno = EBADF;
  913.     return(-1);
  914.  
  915. /*
  916.  *    Timeout or some other error.
  917.  */
  918. sock_err:
  919.     if(newsock_status == -1)    {
  920.         fprintf(stderr, "WATTCP:  %s\n", sockerr(
  921.             sock_table[newsockfd].vp_sockfd));
  922.     }
  923.     if(sock_table[newsockfd].vp_sockfd != NULL)    {
  924.         free(sock_table[newsockfd].vp_sockfd);
  925.         sock_table[newsockfd].vp_sockfd = NULL;
  926.         s_close(newsockfd);
  927.     }
  928.     errno = EBADF;
  929.     return(-1);
  930.  
  931. }
  932.  
  933. /*
  934.  *    Function:    getsockname
  935.  *    Include File:   msdostcp.h
  936.  *    Purpose:    Retrieve the locally bound address of the specified
  937.  *            socket.
  938.  *    Syntax:        int getsockname(int sockfd, struct sockaddr *peer,
  939.  *                int *addlen);
  940.  *    Arguments:    sockfd    specifies the socket for which the local
  941.  *                address is desired.
  942.  *            peer    points to the structure containing the local
  943.  *                address of the specified socket.
  944.  *            addlen    specifies the size of the local address in
  945.  *                bytes.
  946.  *    Return Value:    int    0 success.  The addlen parameter points to
  947.  *                the size of the socket address.
  948.  *                -1 failure and errno set.
  949.  *    Remarks/Portability/Dependencies/Restrictions:
  950.  *        Made for Ms-Dos using the Wattcp library to better conform
  951.  *        to Berkeley sockets in the DOSLYNX WWW project.
  952.  *        This function in no way attempts to be fully compatible with
  953.  *        it's unix namesake.  Many families, types, and protocols
  954.  *        are not supported and are not #defined in the header file.
  955.  *        MsDos does not support many errno values.  The ones supported
  956.  *        will always be returned regardless of the real reason.
  957.  *    Revision History:
  958.  *        12-01-93    created, always fail
  959.  *        03-14-94    modifed to hopefully work in some fashion as
  960.  *                to be expected by Berkeley sockets.
  961.  *        03-14-94    Decided not to modify, Changed WWW library
  962.  *                to not use getsockname by defining POLL_PORTS.
  963.  *        03-17-94    Modified to work with tcp sockets only.
  964.  *                Figured out how along with other function
  965.  *                modifications.
  966.  *        03-22-04    Passing in a bound socket proved to be very
  967.  *                dangerous as we tried to kludge filling in
  968.  *                the address.  A real socket is never created
  969.  *                for a bound socket.  Redefining POLL_PORTS
  970.  *                for HTFTP.c
  971.  */
  972. int getsockname(int sockfd, struct sockaddr *peer, int *addlen)    {
  973. #ifdef WWW
  974.  
  975.     /*
  976.      *    Can't allow access if turned off.
  977.      */
  978.     if(i_networked == 0)    {
  979.         errno = EBADF;
  980.         return(-1);
  981.     }
  982.  
  983.     /*
  984.      *    Need some debugging information.
  985.      */
  986. #ifndef RELEASE
  987.     if(c_trace != 0)    {
  988.         printf("%s:%d: getsockname(%d, peer, %d);\n", __FILE__,
  989.             __LINE__, sockfd, *addlen);
  990.     }
  991. #endif /* RELEASE */
  992. #endif /* WWW */
  993.  
  994.     /*
  995.      *    Set the global socket index
  996.      */
  997.     ssi_sockfd = sockfd;
  998.  
  999.     /*
  1000.      *    Do we have a wattcp socket allocated?
  1001.      */
  1002.     if(sock_table[sockfd].uc_used == 0U)    {
  1003.         /*
  1004.          *    Sorry, return error.
  1005.          */
  1006.         errno = EBADF;
  1007.         return(-1);
  1008.     }
  1009.  
  1010.     /*
  1011.      *    Make sure the socket is of appropriate type.
  1012.      */
  1013.     if(sock_table[sockfd].i_family == AF_INET)    {
  1014.         if(sock_table[sockfd].i_type == SOCK_STREAM)    {
  1015.             if(sock_table[sockfd].i_protocol == IPPROTO_TCP)
  1016.             {
  1017.                 auto struct hack_sockaddr hackpeer;
  1018.                 auto struct sockaddr_in *peer_in;
  1019.  
  1020.                 /*
  1021.                  *    Have wattcp get the information or
  1022.                  *    kludge it if socket not really there.
  1023.                  */
  1024.                 if(sock_table[sockfd].vp_sockfd != NULL)    {
  1025.                     *addlen = sizeof(struct
  1026.                         hack_sockaddr);
  1027.                     hack_getsockname(sock_table[sockfd].
  1028.                         vp_sockfd, &hackpeer, addlen);
  1029.                 }
  1030.                 else    {
  1031.                     /*
  1032.                      *    Try to fill it in.
  1033.                      */
  1034.                     hackpeer.s_ip = sock_table[sockfd].
  1035.                         uli_bindmyaddr;
  1036.                     hackpeer.s_port = sock_table[sockfd].
  1037.                         usi_bindmyport;
  1038.                 }
  1039.  
  1040.                 /*
  1041.                  *    Copy the information over into peer.
  1042.                  *    Assume peer is of type sockaddr_in
  1043.                  */
  1044.                 peer_in = (struct sockaddr_in *)peer;
  1045.                 peer_in->sin_addr.s_addr = hackpeer.s_ip;
  1046.                 peer_in->sin_port = hackpeer.s_port;
  1047.                 peer_in->sin_family = AF_INET;
  1048.  
  1049.                 /*
  1050.                  *    Set the address length.
  1051.                  */
  1052.                 *addlen = sizeof(struct sockaddr_in);
  1053.  
  1054.                 /*
  1055.                  *    Success
  1056.                  */
  1057.                 return(0);
  1058.             }
  1059.         }
  1060.     }
  1061.  
  1062.     /*
  1063.      *    Not supported.
  1064.      */
  1065.     errno = EBADF;
  1066.     return(-1);
  1067. }
  1068.  
  1069. /*
  1070.  *    Function:    s_close
  1071.  *    Include File:   msdostcp.h
  1072.  *    Purpose:    Close a socket connection.
  1073.  *    Syntax:        int s_close(int sockfd);
  1074.  *    Arguments:    sockfd    The socket descriptor to close.
  1075.  *    Return Value:    int    0 on success
  1076.  *                -1 on failure and sets errno.
  1077.  *    Remarks/Portability/Dependencies/Restrictions:
  1078.  *        Made for Ms-Dos using the Wattcp library to better conform
  1079.  *        to Berkeley sockets in the DOSLYNX WWW project.
  1080.  *        This function in no way attempts to be fully compatible with
  1081.  *        it's unix namesake.  Many families, types, and protocols
  1082.  *        are not supported and are not #defined in the header file.
  1083.  *        MsDos does not support many errno values.  The ones supported
  1084.  *        will always be returned regardless of the real reason.
  1085.  *    Revision History:
  1086.  *        11-30-93    created
  1087.  *        03-17-94    Modified to close also, a socket that isn't
  1088.  *                allocate as is the case with the bind, listen,
  1089.  *                accept trio with the listening socket.
  1090.  */
  1091. int s_close(int sockfd)    {
  1092.     auto int sock_status = 0;
  1093.  
  1094.     /*
  1095.      *    Can't allow access if turned off.
  1096.      */
  1097.     if(i_networked == 0)    {
  1098.         errno = EBADF;
  1099.         return(-1);
  1100.     }
  1101.  
  1102.     /*
  1103.      *    Set the global index.
  1104.      */
  1105.     ssi_sockfd = sockfd;
  1106.  
  1107. #ifndef RELEASE
  1108.     if(c_trace)    {
  1109.         printf("%s:%d: s_close(%d);\n", __FILE__, __LINE__, sockfd);
  1110.     }
  1111. #endif /* RELEASE */
  1112.  
  1113.     /*
  1114.      *    First, check to see if this is a valid sockfd
  1115.      */
  1116.     if(sock_table[sockfd].vp_sockfd != NULL)    {
  1117.         /*
  1118.          *     Have wattcp close the connection.
  1119.          *    Account for server sending reset.
  1120.          *    Initiate the close.
  1121.          *    Wait for the close.
  1122.          */
  1123.         sock_tick(sock_table[sockfd].vp_sockfd, &sock_status);
  1124.         sock_close(sock_table[sockfd].vp_sockfd);
  1125.         sock_wait_closed(sock_table[sockfd].vp_sockfd, sock_delay,
  1126.             NULL, &sock_status);
  1127.     }
  1128.  
  1129.     /*
  1130.      *     Regardless if gotoed here by wattcp error, free the socket,
  1131.      *    it's buffer, and return success.
  1132.      */
  1133. sock_err:
  1134.     /*
  1135.      *    Determine here if a socket has a backlog (if it was listening).
  1136.      *    If so, we have to free all sockets that are not establised.
  1137.      */
  1138.     if(sock_table[sockfd].ssi_backlog != 0U &&
  1139.         sock_table[sockfd].ssip_backlogfd != NULL)    {
  1140.         auto int i_back;
  1141.  
  1142.         for(i_back = 0; i_back < (int)(sock_table[sockfd].ssi_backlog)
  1143.             ; i_back++)    {
  1144.  
  1145.             /*
  1146.              *    If there is no socket there, continue on.
  1147.              */
  1148.             if(*(sock_table[sockfd].ssip_backlogfd + i_back) ==
  1149.                 -1)    {
  1150.                 continue;
  1151.             }
  1152.  
  1153.             s_close(*(sock_table[sockfd].ssip_backlogfd +
  1154.                 i_back));
  1155.         }
  1156.  
  1157.         /*
  1158.          *    Free the backlog buffer.
  1159.          */
  1160.         free(sock_table[sockfd].ssip_backlogfd);
  1161.     }
  1162.     sock_table[sockfd].ssi_backlog = 0;
  1163.     sock_table[sockfd].ssip_backlogfd = NULL;
  1164.  
  1165.     /*
  1166.      *    Set the table to indicate a close.
  1167.      */
  1168.     sock_table[sockfd].uc_used = 0U;
  1169.     sock_table[sockfd].usi_EOF =
  1170.         sock_table[sockfd].usi_IO =
  1171.         sock_table[sockfd].usi_OPEN = 0U;
  1172.     sock_table[sockfd].uli_read =
  1173.         sock_table[sockfd].uli_written = 0UL;
  1174.     sock_table[sockfd].uli_bindmyaddr = 0UL;
  1175.     sock_table[sockfd].usi_bindmyport = 0U;
  1176.     if(sock_status == -1 && sock_table[sockfd].vp_sockfd != NULL)
  1177.         fprintf(stderr, "WATTCP:  %s\n", sockerr(sock_table[sockfd].vp_sockfd));
  1178.     if(sock_table[sockfd].vp_sockfd != NULL)    {
  1179.         free(sock_table[sockfd].vp_sockfd);
  1180.         sock_table[sockfd].vp_sockfd = NULL;
  1181.     }
  1182.     return(0);
  1183. }
  1184.  
  1185. /*
  1186.  *    Function:    s_read
  1187.  *    Include File:   msdostcp.h
  1188.  *    Purpose:    Read from a socket connection.
  1189.  *    Syntax:        int s_read(int sockfd, char *buff,
  1190.  *                unsigned int nbytes);
  1191.  *    Arguments:    sockfd    The socket descriptor to read from.
  1192.  *            buff    The buffer to store the amount read.
  1193.  *            nbytes    The number of bytes to read.
  1194.  *    Return Value:    int     The number of bytes successfully read.
  1195.  *                0 on end of file
  1196.  *                -1 on failure and sets errno.
  1197.  *    Remarks/Portability/Dependencies/Restrictions:
  1198.  *        Made for Ms-Dos using the Wattcp library to better conform
  1199.  *        to Berkeley sockets in the DOSLYNX WWW project.
  1200.  *        This function in no way attempts to be fully compatible with
  1201.  *        it's unix namesake.  Many families, types, and protocols
  1202.  *        are not supported and are not #defined in the header file.
  1203.  *        MsDos does not support many errno values.  The ones supported
  1204.  *        will always be returned regardless of the real reason.
  1205.  *    Revision History:
  1206.  *        11-30-93    created
  1207.  */
  1208. int s_read(int sockfd, char *buff, unsigned int nbytes)    {
  1209.     auto signed short int ssi_Status;
  1210.  
  1211.     /*
  1212.      *    Can't allow access if turned off.
  1213.      */
  1214.     if(i_networked == 0)    {
  1215.         errno = EBADF;
  1216.         return(-1);
  1217.     }
  1218.  
  1219.     /*
  1220.      *    Set the global index.
  1221.      */
  1222.     ssi_sockfd = sockfd;
  1223.  
  1224. #ifndef RELEASE
  1225.     if(c_trace)    {
  1226.         printf("%s:%d: s_read(%d, buff, %u);\n", __FILE__, __LINE__,
  1227.             sockfd, nbytes);
  1228.     }
  1229. #endif /* RELEASE */
  1230.  
  1231.     /*
  1232.      *     Make sure socket is valid.
  1233.      */
  1234.     if(sock_table[sockfd].vp_sockfd == NULL)    {
  1235.         errno = EBADF;
  1236.         return(-1);
  1237.     }
  1238.  
  1239.     /*
  1240.      *    Check usi_EOF to send eof, no more reads.
  1241.      *    Provides a way to interrupt wattcp.
  1242.      */
  1243.     if(sock_table[sockfd].usi_EOF)
  1244.         return(0);
  1245.  
  1246.     /*
  1247.      *    Return the number of bytes read.
  1248.      *    Mark that IO took place.  Record total IO.
  1249.      */
  1250.     sock_wait_input(sock_table[sockfd].vp_sockfd, sock_delay, NULL,
  1251.         &ssi_Status);
  1252.     sock_table[sockfd].usi_IO = 1;
  1253.     {
  1254.         short int retval = sock_fastread(sock_table[sockfd].vp_sockfd,
  1255.             buff, nbytes);
  1256.         if(retval > 0)
  1257.             sock_table[sockfd].uli_read += retval;
  1258.         /*
  1259.          *    Assume that sock_wait_input would produce any
  1260.          *    error appropriate, and that a number below zero
  1261.          *    should really be just 0
  1262.          */
  1263.         return(retval < 0 ? 0 : retval);
  1264.     }
  1265.  
  1266. sock_err:
  1267.     /*
  1268.      *    Reaches here only if error occured while waiting for input.
  1269.      */
  1270.     if(ssi_Status == -1 && sock_table[sockfd].vp_sockfd != NULL)
  1271.         fprintf(stderr, "WATTCP:  %s\n", sockerr(sock_table[sockfd].vp_sockfd));
  1272.     return(-1);
  1273. }
  1274.  
  1275. /*
  1276.  *    Function:    s_write
  1277.  *    Include File:   msdostcp.h
  1278.  *    Purpose:    Write to a socket connection.
  1279.  *    Syntax:        int s_read(int sockfd, char *buff,
  1280.  *                unsigned int nbytes);
  1281.  *    Arguments:    sockfd    The socket descriptor to write to.
  1282.  *            buff    The buffer to write.
  1283.  *            nbytes    The number of bytes to write.
  1284.  *    Return Value:    int     The number of bytes successfully writen.
  1285.  *                -1 on failure and sets errno.
  1286.  *    Remarks/Portability/Dependencies/Restrictions:
  1287.  *        Made for Ms-Dos using the Wattcp library to better conform
  1288.  *        to Berkeley sockets in the DOSLYNX WWW project.
  1289.  *        This function in no way attempts to be fully compatible with
  1290.  *        it's unix namesake.  Many families, types, and protocols
  1291.  *        are not supported and are not #defined in the header file.
  1292.  *        MsDos does not support many errno values.  The ones supported
  1293.  *        will always be returned regardless of the real reason.
  1294.  *    Revision History:
  1295.  *        11-30-93    created
  1296.  */
  1297. int s_write(int sockfd, char *buff, unsigned int nbytes)    {
  1298.  
  1299.     /*
  1300.      *    Can't allow access if turned off.
  1301.      */
  1302.     if(i_networked == 0)    {
  1303.         errno = EBADF;
  1304.         return(-1);
  1305.     }
  1306.  
  1307.     /*
  1308.      *    Set the global index.
  1309.      */
  1310.     ssi_sockfd = sockfd;
  1311.  
  1312. #ifndef RELEASE
  1313.     if(c_trace)    {
  1314.         printf("%s:%d: s_write(%d, buff, %u);\n", __FILE__, __LINE__,
  1315.             sockfd, nbytes);
  1316.     }
  1317. #endif /* RELEASE */
  1318.  
  1319.     /*
  1320.      *     Make sure socket is valid.
  1321.      */
  1322.     if(sock_table[sockfd].vp_sockfd == NULL)    {
  1323.         errno = EBADF;
  1324.         return(-1);
  1325.     }
  1326.  
  1327.     /*
  1328.      *    Check usi_EOF to send error.
  1329.      *    Provides a way of interrupting wattcp.
  1330.      */
  1331.     if(sock_table[sockfd].usi_EOF)    {
  1332.         errno = EBADF;
  1333.         return(-1);
  1334.     }
  1335.  
  1336.     /*
  1337.      *    Mark that IO has taken place.  Record total IO.
  1338.      *    Write to the socket, returning what wattcp gives us.
  1339.      */
  1340.     sock_table[sockfd].usi_IO = 1;
  1341.     {
  1342.         short int retval = sock_write(sock_table[sockfd].vp_sockfd,
  1343.             buff, nbytes);
  1344.         if(retval > 0)
  1345.             sock_table[sockfd].uli_written += retval;
  1346.         return(retval);
  1347.     }
  1348. }
  1349.  
  1350. /*
  1351.  *    Function:    gethostbyname
  1352.  *    Include File:   msdostcp.h
  1353.  *    Purpose:    Retrieves host address and name information using
  1354.  *            a host name as a search key.
  1355.  *    Syntax:        struct hostent *gethostbyname(char *hostname);
  1356.  *    Arguments:    hostname    the name of the host to retreive
  1357.  *                    information on.
  1358.  *    Return Value:    struct hostent *    A static hostent structure
  1359.  *                        that will be overwritten
  1360.  *                        on subsequent calls but will
  1361.  *                        hold current information or
  1362.  *                        NULL, unable to resolve the
  1363.  *                        hostname.
  1364.  *    Remarks/Portability/Dependencies/Restrictions:
  1365.  *        Made for Ms-Dos using the Wattcp library to better conform
  1366.  *        to Berkeley sockets in the DOSLYNX WWW project.
  1367.  *        This function in no way attempts to be fully compatible with
  1368.  *        it's unix namesake.  Many families, types, and protocols
  1369.  *        are not supported and are not #defined in the header file.
  1370.  *        MsDos does not support many errno values.  The ones supported
  1371.  *        will always be returned regardless of the real reason.
  1372.  *        There is no h_errno value to be checked upon return, though
  1373.  *        it seems straightforward enough to implement it if need be.
  1374.  *    Revision History:
  1375.  *        11-30-93    created
  1376.  */
  1377. static struct hostent sh_return;
  1378.  
  1379. struct hostent *gethostbyname(char *hostname)    {
  1380.     static char *gethostfirsttime = (char *)1;
  1381.     void free_sh_return(void);
  1382.     unsigned long ul_address;
  1383.  
  1384.     /*
  1385.      *    Can't allow access if turned off.
  1386.      */
  1387.     if(i_networked == 0)    {
  1388.         return(NULL);
  1389.     }
  1390.  
  1391. #ifndef RELEASE
  1392.     if(c_trace)    {
  1393.         printf("%s:%d: gethostbyname(%s);\n", __FILE__, __LINE__,
  1394.             hostname);
  1395.     }
  1396. #endif /* RELEASE */
  1397.  
  1398.     /*
  1399.      *     Is this the first time that any of the msdostcp functions
  1400.      *    are being called?  If so, intialize wattcp and our socket
  1401.      *    interface.
  1402.      */
  1403.     if(firsttime)
  1404.         initialize();
  1405.  
  1406.     /*
  1407.      *     Do this only once for proper initialization of our
  1408.      *    static hostent structure
  1409.      */
  1410.     if(gethostfirsttime != NULL)    {
  1411.         /*
  1412.          *    These will always be the same for now.
  1413.          */
  1414.         sh_return.h_addrtype = AF_INET;
  1415.         sh_return.h_length = sizeof(unsigned long);
  1416.  
  1417.         /*
  1418.          *    Make sure we never do this again.
  1419.          *    Make the name empty.
  1420.          *    Set the aliases and addr_list to a NULL list.
  1421.          */
  1422.         gethostfirsttime = NULL;
  1423.         sh_return.h_name = NULL;
  1424.         sh_return.h_aliases = &gethostfirsttime;
  1425.         sh_return.h_addr_list = &gethostfirsttime;
  1426.  
  1427.         /*
  1428.          *     Finally, at program exit, free all memory we have
  1429.          *    taken.
  1430.          */
  1431.         atexit(free_sh_return);
  1432.     }
  1433.  
  1434.     /*
  1435.      *     First, free all previous contents of our hostent structure.
  1436.      */
  1437.     free_sh_return();
  1438.  
  1439.     /*
  1440.      *     Get the address resolution of the hostname.
  1441.      *    If unable, return NULL.  Remember, no h_errno.
  1442.      */
  1443. #ifdef WWW
  1444.     /*
  1445.      *    To speed up things a bit, keep the return values from resolve
  1446.      *    to help with a network intesive app like a WWW browser.
  1447.      */
  1448.     {
  1449.         extern BeenResolved *BR_first;
  1450.         BeenResolved *BR = NULL;
  1451.  
  1452.         /*
  1453.          *    if there are entries in the list, search for the
  1454.          *    host name.
  1455.          */
  1456.         if(BR_first != NULL)    {
  1457.             for(BR = BR_first; BR != NULL; BR = BR->BR_next)
  1458.             {
  1459.                 if(!strcmp(BR->cp_hostname, hostname))
  1460.                     break;
  1461.             }
  1462.         }
  1463.  
  1464.         /*
  1465.          *    If we found a match, assign in the value.
  1466.          */
  1467.         if(BR != NULL)    {
  1468.             ul_address = BR->uli_address;
  1469.         }
  1470.         /*
  1471.          *    Otherwise, resolve normally.
  1472.          */
  1473.         else    {
  1474.             BeenResolved *BR_new;
  1475.  
  1476.             if(0 == (ul_address = resolve(hostname)))    {
  1477.                 return(NULL);
  1478.             }
  1479.  
  1480.             /*
  1481.              *    Add to the list, if able.
  1482.              *    Otherwise, forget it.
  1483.              */
  1484.             if(NULL != (BR_new = (BeenResolved *)malloc(sizeof(
  1485.                 BeenResolved))))    {
  1486.                 if(BR_first == NULL)    {
  1487.                     BR_first = BR_new;
  1488.                     BR_first->BR_next = NULL;
  1489.                     BR_first->uli_address = ul_address;
  1490.                     BR_first->cp_hostname = (char *)
  1491.                         malloc(strlen(hostname) + 1);
  1492.                     if(BR_first->cp_hostname == NULL)
  1493.                     {
  1494.                         free(BR_first);
  1495.                         BR_first = NULL;
  1496.                     }
  1497.                     else    {
  1498.                         strcpy(BR_first->cp_hostname,
  1499.                             hostname);
  1500.                         /*
  1501.                          *    If firsttime, register
  1502.                          *    function to free list.
  1503.                          */
  1504.                         if(BR_first->BR_next == NULL)
  1505.                             atexit(freeResolved);
  1506.                     }
  1507.                 }
  1508.                 else    {
  1509.                     /*
  1510.                      *    Find last item.
  1511.                      */
  1512.                     for(BR = BR_first; BR->BR_next !=
  1513.                         NULL; BR = BR->BR_next)
  1514.                         ;
  1515.  
  1516.                     BR->BR_next = BR_new;
  1517.                     BR_new->BR_next = NULL;
  1518.                     BR_new->uli_address = ul_address;
  1519.                     BR_new->cp_hostname = (char *)
  1520.                         malloc(strlen(hostname) + 1);
  1521.                     if(BR_new->cp_hostname == NULL)
  1522.                     {
  1523.                         free(BR_new);
  1524.                         BR->BR_next = NULL;
  1525.                     }
  1526.                     else    {
  1527.                         strcpy(BR_new->cp_hostname,
  1528.                             hostname);
  1529.                     }
  1530.                 }
  1531.             }
  1532.         }
  1533.     }
  1534. #else
  1535.     if(0 == (ul_address = resolve(hostname)))
  1536.         return(NULL);
  1537. #endif /* NOT WWW */
  1538.  
  1539.     /*
  1540.      *     We have an address, assign it into h_addr_list.
  1541.      *    Check for no memory.
  1542.      *    Right now, we will only hold the one address resolve()
  1543.      *    returns; though constructed for easier expansion if I ever
  1544.      *    figure out how to correctly do this....
  1545.      */
  1546.     if(NULL == (sh_return.h_addr_list = (char **)malloc(2 *
  1547.         sizeof(char *))))    {
  1548.         sh_return.h_addr_list = &gethostfirsttime;
  1549.         return(NULL);
  1550.     }
  1551.     if(NULL == (*(sh_return.h_addr_list) = (char *)malloc(
  1552.         sizeof(unsigned long))))    {
  1553.         free(sh_return.h_addr_list);
  1554.         sh_return.h_addr_list = &gethostfirsttime;
  1555.         return(NULL);
  1556.     }
  1557.     *((unsigned long *)(*(sh_return.h_addr_list))) = ul_address;
  1558.     *(sh_return.h_addr_list + 1) = NULL;
  1559.  
  1560.     /*
  1561.      *      We must always assume that the hostname passed in is the
  1562.      *    actual hostname since I am unable to implement this currently.
  1563.      *    This means there we be no aliases, ever.  The code was made
  1564.      *    to make this fairly easy to do if you ever need to try and
  1565.      *    know how.
  1566.      */
  1567.     if(NULL == (sh_return.h_name = (char *)malloc(strlen(hostname) + 1)))
  1568.         return(NULL);
  1569.     strcpy(sh_return.h_name, hostname);
  1570.  
  1571.     /*
  1572.      *     Done.
  1573.      */
  1574.     return(&sh_return);
  1575. }
  1576. static void free_sh_return(void)    {
  1577.     /*
  1578.      *    Can't allow access if turned off.
  1579.      */
  1580.     if(i_networked == 0)    {
  1581.         return;
  1582.     }
  1583.  
  1584.     /*
  1585.      *     Free all previous contents of our hostent structure.
  1586.      */
  1587.     if(sh_return.h_name != NULL)
  1588.         free(sh_return.h_name);
  1589.     if(*(sh_return.h_aliases) != NULL)    {
  1590.         auto int i_counter;
  1591.  
  1592.         for(i_counter = 0; *(sh_return.h_aliases + i_counter) != NULL;
  1593.             i_counter++)    {
  1594.             free(*(sh_return.h_aliases + i_counter));
  1595.         }
  1596.         free(sh_return.h_aliases);
  1597.     }
  1598.     if(*(sh_return.h_addr_list) != NULL)    {
  1599.         auto int i_counter;
  1600.  
  1601.         for(i_counter = 0; *(sh_return.h_addr_list + i_counter) != NULL;
  1602.             i_counter++)    {
  1603.             free(*(sh_return.h_addr_list + i_counter));
  1604.         }
  1605.         free(sh_return.h_addr_list);
  1606.     }
  1607. }
  1608.  
  1609. #ifdef WWW
  1610. /*
  1611.  *     The following code has nothing to do with TCP but is included here
  1612.  *    in this file as a matter of convienience for use with the WWW
  1613.  *    DOSLYNX project.
  1614.  */
  1615.  
  1616. /*
  1617.  *    Function:    crypt
  1618.  *    Include File:    msdostcp.h
  1619.  *    Purpose:    Performs basic encryption of data.
  1620.  *    Syntax:        char *crypt(char *key, char *salt);
  1621.  *    Arguments:    key    Specifies an 8 character string which is used
  1622.  *                to change the encryption algorithm.
  1623.  *            salt    Specifies a 2 character string chosen from
  1624.  *                the set ["a-zA-Z0-9./"].  The salt parameter
  1625.  *                is used to vary the hashing algorithm in one
  1626.  *                of 4096 different ways.
  1627.  *    Return Value:    The crypt subroutine returns a pointer to the
  1628.  *            encrypted password.  The first two characters are the
  1629.  *            same as the salt parameter.
  1630.  *    Remarks/Portability/Dependencies/Restrictions:
  1631.  *        Made for Ms-Dos to better conform to unix for the DOSLYNX
  1632.  *        WWW project.  This function in no way attempts to be fully
  1633.  *        compatible with it's unix namesake.  The return value points
  1634.  *        to static data that is overwritten by subsequent calls.
  1635.  *    Revision History:
  1636.  *        12-09-93    created, does nothing sortof to get code up
  1637.  */
  1638. char *crypt(char *key, char *salt)    {
  1639.     static char sc_buffer[11];
  1640.  
  1641.     strcpy(sc_buffer, salt);
  1642.     strcat(sc_buffer, key);
  1643.     return(sc_buffer);
  1644.  
  1645. #ifdef TODO
  1646. #error Complete crypt, source in \www\library\implemen\vms
  1647. #endif /* TODO */
  1648. }
  1649.  
  1650. #ifdef MSDOSMEM
  1651. /*
  1652.  *    The following variables are needed to help with DOS's segmented
  1653.  *    memory scheme and the Borland compiler in the large model, I think(?).
  1654.  *    Sometimes, when passing a pointer as a function argument, the
  1655.  *    validity of it's value is lost.  These variables, in conjunction
  1656.  *    with #ifdef statements help this problem; for now at least....
  1657.  *    If you wish to forgo the use of these variables, simply comment
  1658.  *    out the #define in msdostcp.h.  Using the variables will not cause
  1659.  *    any ill effects other than a minute amount of overhead.  Not
  1660.  *    using them may cause some of the hardest bugs to ever trace down.
  1661.  *    Lastly, all such errors as to be covered by the use of these
  1662.  *    variables are ones that didn't work on my compiler, with my
  1663.  *    setup, etc.  You may or may not have the same problem in different
  1664.  *    or the same functions, I suggest you use this fix if you can find
  1665.  *    these inconsistancies.
  1666.  */
  1667. void *vp_msdosmem;
  1668. void **vpp_msdosmem;
  1669.  
  1670. #endif /* MSDOSMEM */
  1671. #endif /* WWW */
  1672. #endif /* MSDOS */